﻿/* 
    Copyright (c) 2010 Microsoft Corporation.  All rights reserved.
    Use of this sample source code is subject to the terms of the Microsoft license 
    agreement under which you licensed this sample source code and is provided AS-IS.
    If you did not accept the terms of the license agreement, you are not authorized 
    to use this sample source code.  For the terms of the license, please see the 
    license agreement between you and Microsoft.
    
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace PerspectiveFillRate
{

    /// <summary>
    /// This sample show a animated square moving back and forth across the page. You can add and 
    /// delete random rectangles from the page and toggle whether the rectangles have a perspective
    /// transform and/or a storyboard animation applied to them. You will see that the square's animation
    /// gets choppy if a large number of rectangles are added with perspective transforms or storyboard
    /// animations. This is because the rectangles then are cached and contribute to the fill rate. You
    /// will also notice that the squares animation does not get worse when both a perspective transform
    /// and an animation are applied than it is when either one is applied.
    /// </summary>
    public partial class MainPage : PhoneApplicationPage
    {
        private List<Rectangle> _rectList;
        private List<Color> _rectColors;
        private List<Storyboard> _rectStoryboards;
        private Random _rand;
        private bool _isAnimating = false;
        private bool _isPerspective = true;
        
        /// <summary>
        /// The page's constructor. Lists used for the animated rectangles are initialized and the
        /// </summary>
        public MainPage()
        {
            InitializeComponent();
            Application.Current.Host.Settings.EnableFrameRateCounter = true;
            _rectList = new List<Rectangle>();
            _rectStoryboards = new List<Storyboard>();
            _rectColors = new List<Color>() { Colors.Blue, Colors.Red, Colors.Green, Colors.Cyan, Colors.Magenta, Colors.Orange, Colors.Purple, Colors.Yellow, Colors.Brown, Colors.Gray };
            _rand = new Random();


        }
        /// <summary>
        /// Click handler for the Add button. This method creates a new rectangle and adds it to the list.
        /// If _isPerspective is enabled, a new PlaneProjection transform is created and assigned to the rectangle.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addBtn_Click(object sender, RoutedEventArgs e)
        {
            Rectangle newRect = new Rectangle();
            newRect.Height = 400;
            newRect.Width = 160;

            newRect.Fill = new SolidColorBrush(_rectColors[_rand.Next(10)]);
            newRect.SetValue(Canvas.TopProperty, (double)_rand.Next(0, 400));
            newRect.SetValue(Canvas.LeftProperty, (double)_rand.Next(0, 320));


            if (_isPerspective)
            {
                PlaneProjection rectProject = new PlaneProjection();
                rectProject.RotationY = (double)_rand.Next(80);
                newRect.Projection = rectProject;
            }

            _rectList.Add(newRect);

            counter.Text = _rectList.Count.ToString();
            this.LayoutRoot.Children.Add(newRect);

        }
        /// <summary>
        /// Delete button click handler. This method removes a rectangle from the end of the list.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void deleteBtn_Click(object sender, RoutedEventArgs e)
        {
            if (_rectList.Count >= 1)
            {

                this.LayoutRoot.Children.Remove(_rectList[_rectList.Count - 1]);
                _rectList.Remove(_rectList[_rectList.Count - 1]);

                UpdateLayout();
                counter.Text = _rectList.Count.ToString();
            }

        }

        
        /// <summary>
        /// Click handler for the Show button. This method shows the buttons at the bottom of the page.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void showBtn_Click(object sender, RoutedEventArgs e)
        {
            showBtn.Visibility = Visibility.Collapsed;
            hideBtn.Visibility = Visibility.Visible;
            addBtn.Visibility = Visibility.Visible;
            deleteBtn.Visibility = Visibility.Visible;
        }
        /// <summary>
        /// Click handler for the Hide button. This method hides the buttons at the bottom of the page.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hideBtn_Click(object sender, RoutedEventArgs e)
        {
            showBtn.Visibility = Visibility.Visible;
            hideBtn.Visibility = Visibility.Collapsed;
            addBtn.Visibility = Visibility.Collapsed;
            deleteBtn.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// Click handler for the animate button. This method creates a new Storyboard animation for each
        /// rectangle and starts the animation. If the perspective transform is turned off when the animations
        /// are enabled, the animation of the moving square will become choppy. If the perspective transform
        /// is already turned on when animations are enabled, no further degradation in the animation will occur.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void animBtn_Click(object sender, RoutedEventArgs e)
        {
            if (!_isAnimating)
            {
                foreach (Rectangle rectToAnimate in _rectList)
                {
                    TransformGroup rectTransformGroup = new TransformGroup();

                    TranslateTransform rectTranslate = new TranslateTransform();
                    DoubleAnimation rectTranslateX = generateTranslateAnimation();

                    Storyboard.SetTarget(rectTranslateX, rectTranslate);
                    Storyboard.SetTargetProperty(rectTranslateX, new PropertyPath(TranslateTransform.XProperty));

                    rectTransformGroup.Children.Add(rectTranslate);

                    rectToAnimate.RenderTransform = rectTransformGroup;

                    Storyboard rectStoryboard = new Storyboard();

                    rectStoryboard.Children.Add(rectTranslateX);
                    rectStoryboard.Begin();

                    _rectStoryboards.Add(rectStoryboard);
                }
                _isAnimating = true;
            }
            else
            {
                foreach (Storyboard storyboardToStop in _rectStoryboards)
                {
                    storyboardToStop.Stop();
                }
                _rectStoryboards = new List<Storyboard>();
                _isAnimating = false;

            }
            
        }
        /// <summary>
        /// Helper method for generating random animations. Used in the Animation button click handler.
        /// </summary>
        /// <returns></returns>
        public DoubleAnimation generateTranslateAnimation()
        {

            DoubleAnimation rectTranslate = new DoubleAnimation();

            rectTranslate.Duration = new TimeSpan(0, 0, 0, 0, 3000);
            rectTranslate.From = 0;
            rectTranslate.To = 100;
            rectTranslate.AutoReverse = true;
            rectTranslate.RepeatBehavior = RepeatBehavior.Forever;

            return rectTranslate;
        }
        /// <summary>
        /// Click handler for the perspective button. This method creates a new PlaneProjection for each
        /// rectangle. If the animations are turned off when the PlaneProjections are added
        /// the animation of the moving square will become choppy. If the perspective transform
        /// is already turned on when animations are enabled, no further degradation in the animation will occur.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void perspBtn_Click(object sender, RoutedEventArgs e)
        {
            if (_isPerspective)
            {
                foreach (Rectangle rect in _rectList)
                {
                    rect.Projection = null;
                }
                _isPerspective = false;

            }
            else
            {
                foreach (Rectangle rect in _rectList)
                {
                    PlaneProjection rectProject = new PlaneProjection();
                    rectProject.RotationY = (double)_rand.Next(80);
                    rect.Projection = rectProject;
                }
                _isPerspective = true;
            }
        }
        
    }
}
